/*
 * File     : LibraryHelper.java
 * Created  : 22 Apr 2011
 *
 * Copyright © 2011 Matthew Wilson (mj. {my-surname} .uk {at} gmail.com)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.googlecode.dni.internal.library;

import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.nio.ShortBuffer;
import java.util.logging.Level;

import com.googlecode.dni.Warning;
import com.googlecode.dni.internal.DniInternal;
import com.googlecode.dni.type.NativeString;
import com.googlecode.dni.type.ObjectReference;
import com.googlecode.dni.type.Pointer;


/**
 * <p>
 *  Provides helper functions for library calls.
 * </p>
 *
 * @author Matthew Wilson
 */
public final class LibraryHelper
{

    /**
     * Checks whether the user-provided buffer is of the expected size.
     *
     * @param buffer
     *            the buffer
     * @param expectedSize
     *            the expected size
     */
    public static void checkFixedSizeBuffer( final Buffer buffer,
                                             final int expectedSize )
    {
        if ( buffer.capacity() != expectedSize )
        {
            DniInternal.LOGGER.log( Level.WARNING,
                                    "Incorrectly sized buffer passed; expected " + expectedSize
                                        + " but got " + buffer,
                                    new Warning() );
        }
    }

    /**
     * Wraps the given pointer in a buffer.
     *
     * @param pointer
     *            the pointer
     * @param sizeInBytes
     *            the size in bytes
     * @return a buffer
     */
    public static ByteBuffer getByteBuffer( final long pointer,
                                            final int sizeInBytes )
    {
        return DniInternal.MEMORY_ACCESSOR.getBuffer( pointer, sizeInBytes );
    }

    /**
     * Wraps the given pointer in a buffer.
     *
     * @param pointer
     *            the pointer
     * @param sizeInBytes
     *            the size in bytes
     * @return a buffer
     */
    public static CharBuffer getCharBuffer( final long pointer,
                                            final int sizeInBytes )
    {
        return DniInternal.MEMORY_ACCESSOR.getBuffer( pointer, sizeInBytes ).asCharBuffer();
    }

    /**
     * Wraps the given pointer in a buffer.
     *
     * @param pointer
     *            the pointer
     * @param sizeInBytes
     *            the size in bytes
     * @return a buffer
     */
    public static ShortBuffer getShortBuffer( final long pointer,
                                              final int sizeInBytes )
    {
        return DniInternal.MEMORY_ACCESSOR.getBuffer( pointer, sizeInBytes ).asShortBuffer();
    }

    /**
     * Wraps the given pointer in a buffer.
     *
     * @param pointer
     *            the pointer
     * @param sizeInBytes
     *            the size in bytes
     * @return a buffer
     */
    public static IntBuffer getIntBuffer( final long pointer,
                                           final int sizeInBytes )
    {
        return DniInternal.MEMORY_ACCESSOR.getBuffer( pointer, sizeInBytes ).asIntBuffer();
    }

    /**
     * Wraps the given pointer in a buffer.
     *
     * @param pointer
     *            the pointer
     * @param sizeInBytes
     *            the size in bytes
     * @return a buffer
     */
    public static LongBuffer getLongBuffer( final long pointer,
                                            final int sizeInBytes )
    {
        return DniInternal.MEMORY_ACCESSOR.getBuffer( pointer, sizeInBytes ).asLongBuffer();
    }

    /**
     * Wraps the given pointer in a buffer.
     *
     * @param pointer
     *            the pointer
     * @param sizeInBytes
     *            the size in bytes
     * @return a buffer
     */
    public static FloatBuffer getFloatBuffer( final long pointer,
                                              final int sizeInBytes )
    {
        return DniInternal.MEMORY_ACCESSOR.getBuffer( pointer, sizeInBytes ).asFloatBuffer();
    }

    /**
     * Wraps the given pointer in a buffer.
     *
     * @param pointer
     *            the pointer
     * @param sizeInBytes
     *            the size in bytes
     * @return a buffer
     */
    public static DoubleBuffer getDoubleBuffer( final long pointer,
                                                final int sizeInBytes )
    {
        return DniInternal.MEMORY_ACCESSOR.getBuffer( pointer, sizeInBytes ).asDoubleBuffer();
    }

    /**
     * Sets the value of an {@link ObjectReference} that holds a
     * {@link NativeString}.
     *
     * @param reference
     *            the reference
     * @param address
     *            the address
     */
    public static void setNativeStringValue( final ObjectReference< NativeString > reference,
                                             final long address )
    {
        if ( address == 0 )
        {
            reference.setValue( null );
        }
        else
        {
            NativeString value = reference.getValue();
            if ( value == null || value.pointer().address() != address )
            {
                reference.setValue( DniInternal.wrapString( Pointer.fromAddress( address ), Integer.MAX_VALUE ) );
            }
        }
    }

}
